package com.onlyxiahui.extend.query.hibernate.handler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.onlyxiahui.extend.query.hibernate.analysis.sql.CountSqlHandler;
import com.onlyxiahui.extend.query.hibernate.handler.result.BeanResolver;

/**
 * Date 2018-12-28 15:51:20<br>
 * Description
 *
 * @author XiaHui<br>
 * @since 1.0.0
 */
public class BaseHandler {

	public static final String ORDERBY = "order by";

	CountSqlHandler csa = new CountSqlHandler();

	public String wrapTotalSql(String sql) {
//		// 后续可以考虑包装一起
//		List<String> keyList = new ArrayList<>();
//		// sql关键字 用于检查order
//		// by是不是在最后
//		keyList.add(")");
//		keyList.add("where");
//		keyList.add("from");
//		String lower = sql.toLowerCase();
//		// 后续考虑order by 放后面
//		int orderByIndex = lower.lastIndexOf(ORDERBY);
//		StringBuilder sb = new StringBuilder("select count(*) count from (");
//		if (orderByIndex == -1) {
//			return sb.append(sql).append(") totalTable").toString();
//		}
//		// order by 是否在最后
//		boolean boolOrderLast = true;
//		for (String key : keyList) {
//			int keyIndex = sql.lastIndexOf(key);
//			// 解决order by 后面带有()在查询总数sql中存在后在sqlserver2008报错的问题 简单处理，后面有特殊场景在做处理
//			// 修改时间2015年1月9日10:37:09 ys
//			if (keyIndex > orderByIndex) {
//				if (")".equals(key)) {
//					// (所在位置
//					int keyIndex2 = sql.lastIndexOf("(", keyIndex);
//					// (也在order by 后面
//					if (keyIndex2 > orderByIndex) {
//						continue;
//					}
//				}
//				boolOrderLast = false;
//				break;
//			}
//		}
//
//		// 如果order by 为是最后的话 说明该语句排序了 需要把排序去除
//		if (boolOrderLast) {
//			sql = sql.substring(0, orderByIndex);
//		}
//		//sb.append(sql).append(") totalTable").toString();
//		
		return csa.getSmartCountSql(sql, "*");
	}

	Pattern p = Pattern.compile("(?i)order(\\s+)by");

	public String wrapTotalHql(String hql) {

		Matcher m = p.matcher(hql);
		List<String> orderBys = new ArrayList<>();

		while (m.find()) {
			// m.group(1)不包括这两个字符
			String orderBy = (m.group(0));
			orderBys.add(orderBy);

		}

		if (!orderBys.isEmpty()) {
			int size = orderBys.size();
			String orderBy = orderBys.get(size - 1);
			// 后续可以考虑包装一起
			List<String> keyList = new ArrayList<>();
			// sql关键字 用于检查order
			// by是不是在最后
			keyList.add(")");
			keyList.add("where");
			keyList.add("from");

			int orderByIndex = hql.lastIndexOf(orderBy);
			// order by 是否在最后
			boolean boolOrderLast = true;
			for (String key : keyList) {
				int keyIndex = hql.lastIndexOf(key);
				// 解决order by 后面带有()在查询总数sql中存在后在sqlserver2008报错的问题 简单处理，后面有特殊场景在做处理
				if (keyIndex > orderByIndex) {
					if (")".equals(key)) {
						// (所在位置
						int keyIndex2 = hql.lastIndexOf("(", keyIndex);
						// (也在order by 后面
						if (keyIndex2 > orderByIndex) {
							continue;
						}
					}
					boolOrderLast = false;
					break;
				}
			}
			// 如果order by 为是最后的话 说明该语句排序了 需要把排序去除
			if (boolOrderLast) {
				hql = hql.substring(0, orderByIndex);
			}
		}
		// 获取from的下标
		int indexOf = hql.toUpperCase().indexOf("FROM");
		return "select count(*) " + hql.substring(indexOf);
	}

	/**
	 *
	 * Date 2018-12-29 08:54:52<br>
	 * Description 将Map的key转成驼峰命名的方式
	 *
	 * @author XiaHui<br>
	 * @param oldMap
	 * @return
	 * @since 1.0.0
	 */
	Map<String, Object> mapUnderscoreToCamelCase(Map<String, Object> oldMap) {
		Map<String, Object> newMap = null;
		if (oldMap != null) {
			newMap = new HashMap<>(oldMap.size());
			// 循环已有的Map，取出Key转换到javaentity属性名
			Iterator<Entry<String, Object>> iterator = oldMap.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, Object> entry = (Entry<String, Object>) iterator.next();
				newMap.put(filedNameToJavaName(entry.getKey()), entry.getValue());
			}
		}
		return newMap;
	}

	/**
	 *
	 * Date 2018-12-29 08:55:04<br>
	 * Description 表字段名转换java的属性，去掉下划线，比如字段名USER_NAME，属性名为userName
	 *
	 * @author XiaHui<br>
	 * @param fileName
	 * @return
	 * @since 1.0.0
	 */
	String filedNameToJavaName(String fileName) {
		String t = tableNameToClassName(fileName);
		return t.substring(0, 1).toLowerCase() + t.substring(1);
	}

	String tableNameToClassName(String tablename) {
		String[] sa = tablename.split("[_]");
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < sa.length; ++i) {
			sb.append(firstUpper(sa[i]));
		}
		return sb.toString();
	}

	/**
	 * 输入字符串，将第一个字母变成大写，通常用在类名
	 *
	 * @param s:字符串
	 * @return
	 */
	String firstUpper(String s) {
		String lowStr = s.toLowerCase();
		return lowStr.substring(0, 1).toUpperCase() + lowStr.substring(1);
	}

	<T> List<T> mapListToObjectList(List<Map<String, Object>> mapList, Class<T> classType) {
		List<T> list = new ArrayList<>(mapList.size());
		for (Map<String, Object> map : mapList) {
			list.add(mapToObject(map, classType));
		}
		return list;
	}

	<T> T mapToObject(Map<String, Object> dataMap, Class<T> classType) {
		return BeanResolver.beanResolver(classType, dataMap);
	}

	public boolean isPrimitive(Class<?> o) {
		return (o.isPrimitive()) ||
				(o == Integer.class) ||
				(o == Long.class) ||
				(o == Float.class) ||
				(o == Double.class) ||
				(o == Byte.class) ||
				(o == Character.class) ||
				(o == Boolean.class) ||
				(o == Short.class)
				||
				(o == int.class) ||
				(o == long.class) ||
				(o == float.class) ||
				(o == double.class) ||
				(o == byte.class) ||
				(o == char.class) ||
				(o == boolean.class) ||
				(o == short.class);
	}

	public boolean isString(Class<?> o) {
		return (o == String.class);
	}
}
